#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QDebug>
#include <QTextStream>
#include <QIcon>
#include <QSvgRenderer>
#include <QPainter>
#include <QPixmap>
#include <QFileDialog>
#include <QFile>
#include <QTableWidgetItem>
#include <QMessageBox>
#include <QDebug>

// 在构造函数中连接信号和槽
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    controlSocket(new QTcpSocket(this)),
    dataSocket(nullptr),
    dataServer(new QTcpServer(this)),
    m_contextMenu(nullptr),
    m_localContextMenu(nullptr),
    m_downloadAction(nullptr),
    m_deleteAction(nullptr),
    m_uploadAction(nullptr),
    m_uploadedBytes(0),
    m_totalUploadBytes(0),
    m_isPassiveMode(false), // 初始化被动模式标志
    m_passivePort(0) // 初始化被动模式端口
{
    ui->setupUi(this);
    ui->password->setEchoMode(QLineEdit::Password);
    
    // 设置图标
    QIcon connectIcon;
    connectIcon.addFile(":/icons/lianjie.svg");
    ui->connectBtn->setIcon(connectIcon);

    QIcon loginIcon;
    loginIcon.addFile(":/icons/denglu.svg");
    ui->login->setIcon(loginIcon);

    QIcon listIcon;
    listIcon.addFile(":/icons/list.svg");
    ui->listBtn->setIcon(listIcon);

    QIcon downloadIcon;
    downloadIcon.addFile(":/icons/retr.svg");
    ui->downloadBtn->setIcon(downloadIcon);

    QIcon quitIcon;
    quitIcon.addFile(":/icons/quit.svg");
    ui->quitBtn->setIcon(quitIcon);

    // 连接信号槽
    connect(controlSocket, &QTcpSocket::connected, this, [=]() {
        ui->loginInfo->append("connect success");
        });


    connect(controlSocket, &QTcpSocket::readyRead, this, [=]() {
        QByteArray data = controlSocket->readAll();
        strncpy(Respond, data.constData(), MAXSIZE - 1);
        Respond[data.size()] = '\0';
        ui->loginInfo->append(Respond);
        });

    connect(controlSocket, &QTcpSocket::disconnected, this, [=]() {
        ui->loginInfo->append("disconnected from server");
        });

    connect(controlSocket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
        this, [=](QAbstractSocket::SocketError socketError) {
            ui->loginInfo->append("socket error: " + controlSocket->errorString());
        });

    // 连接数据服务器的newConnection信号
    connect(dataServer, &QTcpServer::newConnection, this, &MainWindow::onDataConnected);
    
    // 连接表格右键菜单信号
    connect(ui->fileTable, &QTableWidget::customContextMenuRequested,
        this, &MainWindow::onFileTableContextMenuRequested);

    // 初始化右键菜单
    m_contextMenu = new QMenu(this);
    m_downloadAction = new QAction("下载", this);
    m_deleteAction = new QAction("删除", this);

    // 连接菜单项的触发信号
    connect(m_downloadAction, &QAction::triggered, this, &MainWindow::onDownloadActionTriggered);
    connect(m_deleteAction, &QAction::triggered, this, &MainWindow::onDeleteActionTriggered);

    // 添加菜单项到右键菜单
    m_contextMenu->addAction(m_downloadAction);
    m_contextMenu->addAction(m_deleteAction);
    
    // 初始化本地文件右键菜单
    m_localContextMenu = new QMenu(this);
    m_uploadAction = new QAction("上传", this);
    QAction* m_localDeleteAction = new QAction("删除", this);
    
    // 连接菜单项的触发信号
    connect(m_uploadAction, &QAction::triggered, this, &MainWindow::onUploadActionTriggered);
    connect(m_localDeleteAction, &QAction::triggered, this, [=]() {
        // 显示确认对话框
        QMessageBox::StandardButton reply = QMessageBox::question(this,
            "确认删除",
            QString("确定要删除本地文件 '%1' 吗？").arg(QFileInfo(m_currentLocalContextMenuFile).fileName()),
            QMessageBox::Yes | QMessageBox::No,
            QMessageBox::No);

        if (reply == QMessageBox::Yes) {
            QFile file(m_currentLocalContextMenuFile);
            if (file.remove()) {
                ui->statusInfo->setText("文件删除成功");
                // 删除成功后刷新本地文件列表
                refreshLocalFileList();
            } else {
                QMessageBox::warning(this, "删除失败", "无法删除文件：" + file.errorString());
            }
        }
    });
    
    // 添加菜单项到本地文件右键菜单
    m_localContextMenu->addAction(m_uploadAction);
    m_localContextMenu->addAction(m_localDeleteAction);
    
    // 连接本地文件表格右键菜单信号
    connect(ui->localFileTable, &QTableWidget::customContextMenuRequested,
        this, &MainWindow::onLocalFileTableContextMenuRequested);
    
    // 设置本地文件表格的上下文菜单策略
    ui->localFileTable->setContextMenuPolicy(Qt::CustomContextMenu);

    
    loadSettings();

    // 初始加载当前目录的文件列表
    refreshLocalFileList();

    // 设置表格的上下文菜单策略
    ui->fileTable->setContextMenuPolicy(Qt::CustomContextMenu);

    // 初始化本地文件列表表格
    ui->localFileTable->verticalHeader()->setVisible(false);
    ui->localFileTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);


    // 隐藏行号
    ui->fileTable->verticalHeader()->setVisible(false);
    
    // 设置表头可调整宽度
    ui->fileTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);

    // 连接表格点击信号
    connect(ui->fileTable, &QTableWidget::cellClicked, this, [=](int row, int column) {
        Q_UNUSED(column);
        // 获取文件名并填充到下载框
        QTableWidgetItem *item = ui->fileTable->item(row, 0);
        if (item) {
            // 只对文件类型进行填充，跳过目录
            QTableWidgetItem *typeItem = ui->fileTable->item(row, 1);
            if (typeItem && typeItem->text() == "文件") {
                ui->filename->setText(item->text());
            }
        }
    });
   
}

// 选择本地路径按钮槽函数
void MainWindow::on_selectPathBtn_clicked()
{
    QString path = QFileDialog::getExistingDirectory(this, tr("选择保存路径"), ".", 
                        QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    if (!path.isEmpty()) {
        ui->localPath->setText(path);
        // 选择路径后自动刷新本地文件列表
        loadLocalFileList(path);
    }
}

// 下载按钮槽函数
void MainWindow::on_downloadBtn_clicked()
{
    QString fileName = ui->filename->text();
    QString localPath = ui->localPath->text();
    
    if (fileName.isEmpty()) {
        QMessageBox::warning(this, tr("警告"), tr("请输入要下载的文件名"));
        return;
    }
    
    if (localPath.isEmpty()) {
        QMessageBox::warning(this, tr("警告"), tr("请选择本地保存路径"));
        return;
    }
    
    // 构建完整的本地文件路径
    QString localFilePath = localPath + "/" + fileName;


    // 记录当前下载的文件名
    m_currentDownloadFile = fileName;
    m_downloadedBytesMap[fileName] = 0;

    // 初始化进度条
    ui->downloadProgress->setVisible(true);
    ui->downloadProgress->setValue(0);
    ui->statusInfo->setText(tr("正在下载文件: ") + fileName);

    RETRRequest();
}

// 更新下载进度
void MainWindow::updateDownloadProgress(qint64 readBytes, qint64 totalBytes)
{
    if (totalBytes > 0) {
        int progress = (int)((readBytes * 100) / totalBytes);
        ui->downloadProgress->setValue(progress);
    }
}

// 下载完成处理
void MainWindow::downloadFinished()
{
    ui->downloadProgress->setVisible(false);
    ui->statusInfo->setText(tr("下载完成"));
    QMessageBox::information(this, tr("提示"), tr("文件下载完成"));
    // 下载完成后刷新本地文件列表
    refreshLocalFileList();
}

// 右键菜单请求处理槽函数
void MainWindow::onFileTableContextMenuRequested(const QPoint& pos)
{
    // 获取右键点击的单元格所在的行
    int row = ui->fileTable->rowAt(pos.y());
    int column = ui->fileTable->columnAt(pos.x());

    // 只有当点击在有效行范围内（且列也有效）时才处理
    if (row < 0 || row >= ui->fileTable->rowCount() || column < 0) {
        return; // 点击在空白区域，不显示菜单
    }

    // 获取文件名和类型
    QTableWidgetItem* nameItem = ui->fileTable->item(row, 0);
    QTableWidgetItem* typeItem = ui->fileTable->item(row, 1);

    if (!nameItem || !typeItem) return;

    // 只有当点击的是文件类型时才显示右键菜单
    if (typeItem->text() == "文件") {
        // 保存当前右键点击的文件名
        m_currentContextMenuFile = nameItem->text();

        // 显示右键菜单
        m_contextMenu->exec(ui->fileTable->mapToGlobal(pos));
    }
}

// 本地文件右键菜单请求处理槽函数
void MainWindow::onLocalFileTableContextMenuRequested(const QPoint& pos)
{
    // 获取右键点击的单元格所在的行
    int row = ui->localFileTable->rowAt(pos.y());
    int column = ui->localFileTable->columnAt(pos.x());

    // 只有当点击在有效行范围内（且列也有效）时才处理
    if (row < 0 || row >= ui->localFileTable->rowCount() || column < 0) {
        return; // 点击在空白区域，不显示菜单
    }

    // 获取文件名和类型
    QTableWidgetItem* nameItem = ui->localFileTable->item(row, 0);
    QTableWidgetItem* typeItem = ui->localFileTable->item(row, 1);

    if (!nameItem || !typeItem) return;

    // 只有当点击的是文件类型时才显示右键菜单
    if (typeItem->text() == "文件") {
        // 保存当前右键点击的本地文件名（完整路径）
        QString fileName = nameItem->text();
        QString path = ui->localPath->text();
        m_currentLocalContextMenuFile = QDir(path).absoluteFilePath(fileName);

        // 显示右键菜单
        m_localContextMenu->exec(ui->localFileTable->mapToGlobal(pos));
    }
}

// 下载菜单项触发槽函数
void MainWindow::onDownloadActionTriggered()
{
    // 将文件名填充到下载框
    ui->filename->setText(m_currentContextMenuFile);

    // 自动触发下载按钮的点击事件
    on_downloadBtn_clicked();
}

// 删除菜单项触发槽函数
void MainWindow::onDeleteActionTriggered()
{
    // 显示确认对话框
    QMessageBox::StandardButton reply = QMessageBox::question(this,
        "确认删除",
        QString("确定要删除文件 '%1' 吗？").arg(m_currentContextMenuFile),
        QMessageBox::Yes | QMessageBox::No,
        QMessageBox::No);

    if (reply == QMessageBox::Yes) {
        // 发送删除命令
        if (DELETERequest(m_currentContextMenuFile)) {
            // 删除成功后刷新文件列表
            on_listBtn_clicked();
        }
        else {
            QMessageBox::warning(this, "删除失败", "无法删除文件，请检查权限或网络连接。");
        }
    }
}

// 上传菜单项触发槽函数
void MainWindow::onUploadActionTriggered()
{
    // 检查是否已连接到服务器
    if (controlSocket->state() != QTcpSocket::ConnectedState) {
        QMessageBox::warning(this, "警告", "请先连接到FTP服务器");
        return;
    }

    // 检查文件是否存在
    QFileInfo fileInfo(m_currentLocalContextMenuFile);
    if (!fileInfo.exists() || !fileInfo.isFile()) {
        QMessageBox::warning(this, "警告", "文件不存在或不是有效的文件");
        return;
    }

    // 获取文件名（不包含路径）
    QString fileName = fileInfo.fileName();

    // 显示确认对话框
    QMessageBox::StandardButton reply = QMessageBox::question(this,
        "确认上传",
        QString("确定要上传文件 '%1' 到服务器吗？").arg(fileName),
        QMessageBox::Yes | QMessageBox::No,
        QMessageBox::No);

    if (reply == QMessageBox::Yes) {
        // 发送上传请求
        if (STORRequest(m_currentLocalContextMenuFile, fileName)) {
            ui->statusInfo->setText("正在上传文件: " + fileName);
        }
        else {
            QMessageBox::warning(this, "上传失败", "无法开始上传文件，请检查权限或网络连接。");
        }
    }
}

// 实现DELETERequest函数，发送DELETE命令删除文件
bool MainWindow::DELETERequest(const QString& filename)
{
    ui->loginInfo->append("正在删除文件: " + filename);

    // 构建DELE命令
    QString cmd = "DELE " + filename + "\r\n";

    // 发送命令到FTP服务器
    controlSocket->write(cmd.toUtf8());
    controlSocket->flush();

    // 等待服务器响应
    Respond[0] = 0;
    if (!controlSocket->waitForReadyRead(5000)) {
        ui->loginInfo->append("删除超时");
        return false;
    }

    // 检查响应码，250表示删除成功
    int code = RespondCode(Respond);
    return (code == 250);
}

// 实现STORRequest函数，发送STOR命令上传文件
bool MainWindow::STORRequest(const QString& localFilePath, const QString& remoteFileName)
{
    ui->loginInfo->append("正在上传文件: " + localFilePath);

    if (false == m_isPassiveMode) {
        // 1. 确保数据连接已经建立
        if (!dataServer->isListening()) {
            if (!DataConnect()) {
                ui->loginInfo->append("数据连接建立失败");
                ui->statusInfo->setText("下载失败");
                ui->downloadProgress->setVisible(false);
                return false;
            }
        }

        // 2. 发送PORT命令
        if (!PORTRequest()) {
            ui->loginInfo->append("PORT命令失败");
            ui->statusInfo->setText("下载失败");
            ui->downloadProgress->setVisible(false);
            return false;
        }
    }
    else {
        if (nullptr == dataSocket || false == m_isPassiveMode2) {
            if (!PASVRequest()) {
                ui->loginInfo->append("PASV命令失败");
                ui->statusInfo->setText("上传失败");
                ui->downloadProgress->setVisible(false);
                return false;
            }
        }
    }

    // 保存当前上传的文件名
    m_currentUploadFile = localFilePath;

    // 获取文件大小
    QFileInfo fileInfo(localFilePath);
    m_totalUploadBytes = fileInfo.size();
    m_uploadedBytes = 0;

    // 设置当前命令为STOR
    setCurCmd("STOR " + remoteFileName);

    // 构建STOR命令
    QString cmd = "STOR " + remoteFileName + "\r\n";

    // 发送命令到FTP服务器
    controlSocket->write(cmd.toUtf8());
    controlSocket->flush();

    // 等待服务器响应
    Respond[0] = 0;
    if (!controlSocket->waitForReadyRead(5000)) {
        ui->loginInfo->append("上传超时");
        return false;
    }

    // 检查响应码，150表示准备接收数据
    int code = RespondCode(Respond);
    if (code == 150 || code == 125) {
        // 在被动模式下，客户端主动连接服务器的数据端口
            // 打开本地文件并开始发送数据
            QFile* file = new QFile(m_currentUploadFile);
            if (!file->open(QIODevice::ReadOnly)) {
                ui->loginInfo->append("无法打开本地文件: " + file->errorString());
                ui->statusInfo->setText("上传失败");
                delete file;
            }
            else {
                // 插入到映射中
                m_mapSocketFile.insert(dataSocket, file);

                // 连接bytesWritten信号以追踪上传进度
                connect(dataSocket, &QTcpSocket::bytesWritten,
                    this, &MainWindow::onDataBytesWritten);

                // 开始发送文件数据
                const int chunkSize = 4096;
                QByteArray chunk = file->read(chunkSize);
                if (!chunk.isEmpty()) {
                    dataSocket->write(chunk);
                    m_uploadedBytes += chunk.size();
                }
                return true;
            }
    }
    return false;
}

MainWindow::~MainWindow()
{
    // 保存设置
    saveSettings();
    
    // 关闭并释放网络资源
    if (controlSocket->isOpen())
        controlSocket->close();
    if (dataSocket && dataSocket->isOpen())
        dataSocket->close();
    if (dataServer->isListening())
        dataServer->close();
    
    delete ui;
}

/*
 * 控制连接
 */
bool MainWindow::ControlConnect(){
    m_Address = ui->address->text();
    
    ui->loginInfo->append("connect to server...");
    
    // 使用Qt的QTcpSocket进行连接
    controlSocket->connectToHost(m_Address, m_serverPort);
    
    // 等待连接成功或失败
    if (!controlSocket->waitForConnected(5000)) {
        ui->loginInfo->append("connect error: " + controlSocket->errorString() + "server: "+ m_Address + ":" + QString::number(m_serverPort));
        return false;
    }

    if (dataSocket) {
        dataSocket->close();
        dataSocket->deleteLater();
        dataSocket = nullptr;
    }
    
    // 等待服务器响应
    if (controlSocket->waitForReadyRead(3000)) {
        QByteArray data = controlSocket->readAll();
        strncpy(Respond, data.constData(), MAXSIZE - 1);
        Respond[data.size()] = '\0';
        ui->loginInfo->append("receive success");
        ui->loginInfo->append(Respond);
        ui->loginInfo->append("--------------------------");
        QMessageBox::information(NULL,"info","controlConnect to ftpserver\r\n success",QMessageBox::Yes);
        return true;
    } else {
        ui->loginInfo->append("receive error: " + controlSocket->errorString());
        return false;
    }
}

/**
 * @brief MainWindow::FTPLogin
 * @return
 * 用户登录
 */
bool MainWindow::FTPLogin(){
    m_Username = ui->username->text();
    m_Password = ui->password->text();
    
    // 发送用户名
    QString userCommand = "USER " + m_Username + "\r\n";
    qDebug() << "Sending: " << userCommand;
    controlSocket->write(userCommand.toUtf8());
    
    if (!controlSocket->waitForBytesWritten(3000)) {
        ui->loginInfo->append("socket username send error: " + controlSocket->errorString());
        return false;
    }
    
    ui->loginInfo->append("socket username send success");
    
    // 等待服务器响应
    if (controlSocket->waitForReadyRead(3000)) {
        QByteArray data = controlSocket->readAll();
        strncpy(Respond, data.constData(), MAXSIZE - 1);
        Respond[data.size()] = '\0';
        ui->loginInfo->append(Respond);
    } else {
        ui->loginInfo->append("socket username receive error: " + controlSocket->errorString());
        return false;
    }
    
    ui->loginInfo->append("password login...");
    
    // 发送密码
    QString passCommand = "PASS " + m_Password + "\r\n";
    controlSocket->write(passCommand.toUtf8());
    
    if (!controlSocket->waitForBytesWritten(3000)) {
        ui->loginInfo->append("socket password send error: " + controlSocket->errorString());
        return false;
    }
    
    ui->loginInfo->append("socket password send success");
    
    // 等待服务器响应
    if (controlSocket->waitForReadyRead(3000)) {
        QByteArray data = controlSocket->readAll();
        strncpy(Respond, data.constData(), MAXSIZE - 1);
        Respond[data.size()] = '\0';
        ui->loginInfo->append(Respond);
    } else {
        ui->loginInfo->append("socket password receive error: " + controlSocket->errorString());
        return false;
    }
    
    return true;
}

/**
 * @brief MainWindow::DataConnect
 * @return
 * 数据连接--主动
 */
bool MainWindow::DataConnect(){
    if (m_isPassiveMode) {
        return true; // 被动模式下，连接由调用方处理
    }

    // 使用Qt的QTcpServer创建数据连接
    if (dataServer->isListening()) {
        dataServer->close();
    }
    
    // 监听任意地址的随机端口
    if (!dataServer->listen(QHostAddress::Any, 0)) {
        ui->loginInfo->append("data server listen error: " + dataServer->errorString());
        return false;
    }
    
    ui->loginInfo->append("data server started on port: " + QString::number(dataServer->serverPort()));
    return true;
}

/**
 * @brief MainWindow::onDataConnected
 * 当数据连接建立时调用
 */
void MainWindow::onDataConnected() {
    // 如果是被动模式，这个函数不应该被调用，因为数据连接是由客户端主动建立的
    if (m_isPassiveMode) {
        ui->loginInfo->append("警告：在被动模式下不应该调用onDataConnected");
        return;
    }

    // 获取新建立的连接
    dataSocket = dataServer->nextPendingConnection();
    QString cmd = getCurCmd();
    
    if (cmd.startsWith("RETR")) {
        // 下载逻辑（保持不变）
        QString filename = cmd.mid(5, cmd.size() - 7);//"RETR \r\n"
        QDir dir(ui->localPath->text());
        QString savePath = dir.absoluteFilePath(filename);
        QFile* file = new QFile(savePath);

        if (!file->open(QIODevice::WriteOnly | QIODevice::Truncate)) {
            ui->loginInfo->append("无法创建文件: " + file->errorString());
            ui->statusInfo->setText("下载失败");
            ui->downloadProgress->setVisible(false);
        }
        else {
            ui->downloadProgress->setVisible(true);
        }
        m_mapSocketFile.insert(dataSocket, file);
    }
    else if (cmd.startsWith("STOR")) {
        // 上传逻辑（新增）
        QFile* file = new QFile(m_currentUploadFile);
        
        if (!file->open(QIODevice::ReadOnly)) {
            ui->loginInfo->append("无法打开本地文件: " + file->errorString());
            ui->statusInfo->setText("上传失败");
            delete file;
        } else {
            // 插入到映射中
            m_mapSocketFile.insert(dataSocket, file);
            
            // 连接bytesWritten信号以追踪上传进度
            connect(dataSocket, &QTcpSocket::bytesWritten,
                this, &MainWindow::onDataBytesWritten);
            
            // 开始发送文件数据
            const int chunkSize = 4096;
            QByteArray chunk = file->read(chunkSize);
            if (!chunk.isEmpty()) {
                dataSocket->write(chunk);
                m_uploadedBytes += chunk.size();
            }
        }
    }
    
    // 连接数据读取信号
    connect(dataSocket, &QTcpSocket::readyRead, this, &MainWindow::onDataReadyRead);
    connect(dataSocket, &QTcpSocket::disconnected, this, [=]() {
        QTcpSocket* pSocket = dynamic_cast<QTcpSocket*>(sender());
        if (pSocket) {
            if (m_mapSocketFile.contains(pSocket)) {
                QFile* file = m_mapSocketFile[pSocket];
                file->close();
                delete file;
                m_mapSocketFile.remove(pSocket);
                
                QString cmd = getCurCmd();
                if (cmd.startsWith("RETR")) {
                    QTimer::singleShot(100, this, &MainWindow::downloadFinished);
                } else if (cmd.startsWith("STOR")) {
                    QTimer::singleShot(100, this, &MainWindow::uploadFinished);
                }
                
                ui->loginInfo->append("data connection closed");
            }
            pSocket->deleteLater();
            dataSocket = nullptr;
        }
    });
    
    ui->loginInfo->append("data connection established");
}

/**
 * @brief MainWindow::onDataReadyRead
 * 当有数据可读时调用
 */
void MainWindow::onDataReadyRead() {
    // 注意：这个函数需要根据不同的命令进行不同的处理
    // 在实际应用中，应该根据当前正在执行的FTP命令来决定如何处理数据
    QTcpSocket * pSocket = dynamic_cast<QTcpSocket *>(sender());
    if (pSocket) {
        QByteArray data = pSocket->readAll();

        if (m_mapSocketFile.contains(pSocket)) {
            QFile* file = m_mapSocketFile[pSocket];
            // 写入数据
            qint64 bytesWritten = file->write(data);

            // 更新已下载字节数
            if (!m_currentDownloadFile.isEmpty()) {
                m_downloadedBytesMap[m_currentDownloadFile] += bytesWritten;

                // 计算进度
                qint64 totalSize = m_fileSizeMap.value(m_currentDownloadFile, 0);
                if (totalSize > 0) {
                    qint64 downloadedSize = m_downloadedBytesMap[m_currentDownloadFile];
                    updateDownloadProgress(downloadedSize, totalSize);
                    if (m_downloadedBytesMap[m_currentDownloadFile] >= totalSize) {
                        file->close();
                        delete file;
                        m_mapSocketFile.remove(pSocket);

                        QString cmd = getCurCmd();
                        if (cmd.startsWith("RETR")) {
                            QTimer::singleShot(100, this, &MainWindow::downloadFinished);
                        }
                    }
                }
            }
        } else {
            // 将数据转换为字符串并解析为表格格式
            QString listData = QString::fromUtf8(data);
            parseFTPList(listData);
            ui->infoTabs->setCurrentWidget(ui->fileTab);
        }
    }
}

// 数据发送完成信号处理槽函数
void MainWindow::onDataBytesWritten(qint64 bytes)
{
    // 更新上传进度
    if (m_totalUploadBytes > 0) {
        int progress = static_cast<int>((m_uploadedBytes * 100.0) / m_totalUploadBytes);
        ui->statusInfo->setText(QString("正在上传: %1%").arg(progress));
    }

    // 继续发送数据
    if (dataSocket && m_mapSocketFile.contains(dataSocket)) {
        QFile* file = m_mapSocketFile[dataSocket];
        if (file->atEnd()) {
            if (false == m_isPassiveMode2) {
                // 文件发送完成，关闭数据连接
                dataSocket->disconnectFromHost();
            }
            else {
                FISTORRequest(m_totalUploadBytes);
            }
            file->close();
            delete file;
            m_mapSocketFile.remove(dataSocket);
            QTimer::singleShot(100, this, &MainWindow::uploadFinished);
        }
        else {
            // 继续发送下一块数据
            const int chunkSize = 4096;
            QByteArray chunk = file->read(chunkSize);
            if (!chunk.isEmpty()) {
                dataSocket->write(chunk);
                m_uploadedBytes += chunk.size();
            }
        }
    }
}

// 上传完成槽函数
void MainWindow::uploadFinished()
{
    ui->statusInfo->setText("上传完成");
    ui->loginInfo->append("文件上传完成: " + m_currentUploadFile);

    // 刷新远程文件列表
    on_listBtn_clicked();

    // 重置上传状态
    m_currentUploadFile.clear();
    m_uploadedBytes = 0;
    m_totalUploadBytes = 0;
}

// 解析FTP列表并显示到表格
void MainWindow::parseFTPList(const QString &listData) {
    // 清空表格
    //ui->fileTable->setRowCount(0);
    
    // 按行分割数据
    QStringList lines = listData.split("\n", Qt::SkipEmptyParts);
    
    foreach (QString line, lines) {
        line = line.trimmed();
        if (line.isEmpty()) continue;
        
        // 解析FTP列表行
        // 格式如: -rwxr-xr-x    1 0        0             881 Sep 29 17:37 1.kmz
        QStringList parts = line.split(QRegExp("\\s+"), Qt::SkipEmptyParts);
        int nCol = parts.size();
        if ( nCol >= 8) {
            // 确定是否为目录
            QString type = (parts[0].startsWith('d')) ? "目录" : "文件";
            
            // 文件名 (可能包含空格，所以需要特殊处理)
            QString filename;
            bool bFewField = nCol == 8;
            int nameIndex = bFewField ? 7:8; // 文件名通常从第9个字段开始
            while (nameIndex < parts.size()) {
                if (!filename.isEmpty()) filename += " ";
                filename += parts[nameIndex];
                nameIndex++;
            }
            
            int startIndex = bFewField ? 3 : 4;
            // 文件大小
            QString sizeStr = parts[startIndex++];
            qint64 size = sizeStr.toLongLong();
            // 只有文件类型才存储大小信息
            if (type == "文件") {
                m_fileSizeMap[filename] = size;
            }
            // 创建时间
            
            QString month = parts[startIndex++];
            QString day = parts[startIndex++];
            QString timeYear = parts[startIndex++];
            QString date = QString("%1 %2 %3").arg(month).arg(day).arg(timeYear);
            
            // 添加到表格 - 调整顺序：先文件名，再类型
            int row = ui->fileTable->rowCount();
            ui->fileTable->insertRow(row);
            
            ui->fileTable->setItem(row, 0, createTableItem(filename)); // 文件名
            ui->fileTable->setItem(row, 1, createTableItem(type));    // 类型
            ui->fileTable->setItem(row, 2, createTableItem(sizeStr));    // 大小
            ui->fileTable->setItem(row, 3, createTableItem(date));    // 创建时间
        }
    }
    
    // 确保表头宽度设置为可交互（用户可调）
    // 注意：不再设置自动调整模式，让用户可以自由调整
}

// 加载本地文件列表
void MainWindow::loadLocalFileList(const QString& path)
{
    // 清空表格
    ui->localFileTable->setRowCount(0);

    QDir dir(path);
    if (!dir.exists()) {
        return;
    }

    // 获取目录中的所有文件和子目录
    QFileInfoList fileList = dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot,
        QDir::DirsFirst | QDir::Name);

    foreach(QFileInfo fileInfo, fileList) {
        int row = ui->localFileTable->rowCount();
        ui->localFileTable->insertRow(row);

        // 文件名
        ui->localFileTable->setItem(row, 0, createTableItem(fileInfo.fileName()));

        // 类型
        QString type = fileInfo.isDir() ? "目录" : "文件";
        ui->localFileTable->setItem(row, 1, createTableItem(type));

        // 大小
        QString sizeStr = "-";
        if (fileInfo.isFile()) {
            qint64 size = fileInfo.size();
            // 格式化大小显示
            if (size < 1024) {
                sizeStr = QString::number(size) + " B";
            }
            else if (size < 1024 * 1024) {
                sizeStr = QString::number(size / 1024.0, 'f', 2) + " KB";
            }
            else {
                sizeStr = QString::number(size / (1024.0 * 1024.0), 'f', 2) + " MB";
            }
        }
        ui->localFileTable->setItem(row, 2, createTableItem(sizeStr));

        // 创建时间
        QString date = fileInfo.lastModified().toString("yyyy-MM-dd HH:mm:ss");
        ui->localFileTable->setItem(row, 3, createTableItem(date));
    }
}

// 创建表格项的辅助函数
QTableWidgetItem *MainWindow::createTableItem(const QString &text, bool editable) {
    QTableWidgetItem *item = new QTableWidgetItem(text);
    item->setFlags(editable ? item->flags() : (item->flags() & ~Qt::ItemIsEditable));
    return item;
}
void MainWindow::setCurCmd(QString cmd)
{
    m_lockCmd.lock();
    m_ftpCmd = cmd;
    m_lockCmd.unlock();
}

QString MainWindow::getCurCmd()
{
    QString cmd;
    m_lockCmd.lock();
    cmd = m_ftpCmd;
    m_lockCmd.unlock();
    return cmd;
}


bool MainWindow::PORTRequest(){
    ui->loginInfo->append("PORT....");
    
    // 获取本机IP地址和数据服务器端口
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    QHostAddress localIp;
    QHostAddress localIp2;

    QString serverIp = ui->address->text();
    int start = 0;
    for (int i = 0;i <2;i++) {
        start = serverIp.indexOf(".", start+1);
    }

    QString serverPrefix = serverIp.mid(0, start+1);
    

    
    // 找到
    for (int i = 0; i < ipAddressesList.size(); ++i) {
        if (!ipAddressesList.at(i).isLoopback() && ipAddressesList.at(i).protocol() == QAbstractSocket::IPv4Protocol) {
            localIp = ipAddressesList.at(i);
            if (localIp.toString().startsWith(serverPrefix)) {
                break;
            }
        }
    }
    
    // 如果没有找到，使用回环地址
    if (localIp.isNull()) {
        localIp = QHostAddress(QHostAddress::LocalHost);
    }
    
    // 将IP地址转换为FTP PORT命令格式
    QString ip = localIp.toString();
    QStringList ipParts = ip.split(".");
    int port = dataServer->serverPort();
    int p1 = port / 256;
    int p2 = port % 256;
    
    QString portCommand = QString("PORT %1,%2,%3,%4,%5,%6\r\n")
                          .arg(ipParts[0]).arg(ipParts[1]).arg(ipParts[2]).arg(ipParts[3])
                          .arg(p1).arg(p2);
    
    // 发送PORT命令
    controlSocket->write(portCommand.toUtf8());
    
    if (!controlSocket->waitForBytesWritten(3000)) {
        ui->loginInfo->append("PORT Request Error: " + controlSocket->errorString());
        return false;
    }
    
    ui->loginInfo->append(portCommand);
    
    // 等待服务器响应
    if (controlSocket->waitForReadyRead(3000)) {
        QByteArray data = controlSocket->readAll();
        strncpy(Respond, data.constData(), MAXSIZE - 1);
        Respond[data.size()] = '\0';
        ui->loginInfo->append(Respond);
        return true;
    } else {
        ui->loginInfo->append("receive portmessage error: " + controlSocket->errorString());
        return false;
    }
}

// 实现PASVRequest函数，发送PASV命令进入被动模式
bool MainWindow::PASVRequest()
{
    // 构建PASV命令
    QString cmd;
    if (false == m_isPassiveMode2) {
        ui->loginInfo->append("进入被动模式(PASV)...");
        cmd = "PASV\r\n";
    }
    else {
        ui->loginInfo->append("进入被动模式(PASV2)...");
        cmd = "PASV2\r\n";
    }

    // 发送命令到FTP服务器
    controlSocket->write(cmd.toUtf8());
    controlSocket->flush();

    // 等待服务器响应
    Respond[0] = 0;
    if (!controlSocket->waitForReadyRead(5000)) {
        ui->loginInfo->append("PASV命令超时");
        return false;
    }

    // 检查响应码，227表示被动模式已接受
    int code = RespondCode(Respond);
    if (code != 227) {
        ui->loginInfo->append("进入被动模式失败");
        return false;
    }

    // 解析响应获取IP地址和端口号
    // 响应格式示例: "227 Entering Passive Mode (192,168,1,1,128,129)"
    QString respondStr = Respond;
    QRegExp rx("\\((\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)\\)");
    if (rx.indexIn(respondStr) != -1) {
        // 提取IP地址的四个部分
        QString ip = rx.cap(1) + "." + rx.cap(2) + "." + rx.cap(3) + "." + rx.cap(4);

        // 计算端口号 = 高位字节 * 256 + 低位字节
        int portHigh = rx.cap(5).toInt();
        int portLow = rx.cap(6).toInt();
        quint16 port = portHigh * 256 + portLow;

        // 保存被动模式信息
        m_passiveAddress.setAddress(ip);
        m_passivePort = port;
        dataSocket = new QTcpSocket(this);
        dataSocket->connectToHost(m_passiveAddress, m_passivePort);
        // 连接数据读取信号
        connect(dataSocket, &QTcpSocket::readyRead, this, &MainWindow::onDataReadyRead);

        ui->loginInfo->append(QString("已进入被动模式，服务器地址: %1，端口: %2").arg(ip).arg(port));
        return true;
    }
    else {
         ui->loginInfo->append("无法解析PASV响应");
         return false;
    }
}


/**
 * @brief MainWindow::LISTRequest
 * @return
 */
bool MainWindow::LISTRequest(){
    // 清空目录信息显示
    ui->fileTable->clearContents();
    ui->fileTable->setRowCount(0);
    
    // 设置状态栏信息
    ui->statusInfo->setText("正在获取文件列表...");
    
    // 发送LIST命令
    QString listCommand = "LIST\r\n";
    setCurCmd(listCommand);
    controlSocket->write(listCommand.toUtf8());
    
    if (!controlSocket->waitForBytesWritten(3000)) {
        ui->loginInfo->append("发送LIST命令错误: " + controlSocket->errorString());
        ui->statusInfo->setText("获取文件列表失败");
        return false;
    }
    
    ui->loginInfo->append("发送LIST命令成功");
    
    // 等待服务器响应
    if (controlSocket->waitForReadyRead(3000)) {
        QByteArray data = controlSocket->readAll();
        strncpy(Respond, data.constData(), MAXSIZE - 1);
        Respond[data.size()] = '\0';
        ui->loginInfo->append("接收LIST响应成功");
        ui->loginInfo->append(Respond);
    } else {
        ui->loginInfo->append("接收LIST响应错误: " + controlSocket->errorString());
        ui->statusInfo->setText("获取文件列表失败");
        return false;
    }
    
    // 注意：数据连接的建立和数据读取由onDataConnected()和onDataReadyRead()槽函数处理
    // 这里不需要像原来那样手动accept和recv
    
    return true;
}

/**
 * @brief MainWindow::QUITRequest
 * @return
 * 使用QUIT命令
 */
bool MainWindow::QUITRequest(){
    // 发送QUIT命令
    QString quitCommand = "QUIT\r\n";
    controlSocket->write(quitCommand.toUtf8());
    
    if (!controlSocket->waitForBytesWritten(3000)) {
        ui->loginInfo->append("quit ftp request error: " + controlSocket->errorString());
        return false;
    }
    
    ui->loginInfo->append("quit ftp send success");
    
    // 等待服务器响应
    if (controlSocket->waitForReadyRead(3000)) {
        QByteArray data = controlSocket->readAll();
        strncpy(Respond, data.constData(), MAXSIZE - 1);
        Respond[data.size()] = '\0';
        ui->loginInfo->append("quit success");
        ui->loginInfo->append(Respond);
    } else {
        ui->loginInfo->append("quit ftp receive error: " + controlSocket->errorString());
    }
    
    // 关闭连接
    controlSocket->close();
    
    if(QMessageBox::information(NULL,"info","quit ftpserver\r\n success",QMessageBox::Yes)){
        this->close();
    }
    
    return true;
}


/**
 * @brief MainWindow::RETRRequest
 * @return
 * 下载文件
 */
bool MainWindow::RETRRequest(){
    QString filename = ui->filename->text();
    
    if(filename.isEmpty()){
        QMessageBox::warning(NULL,"错误","请输入文件名",QMessageBox::Yes);
        return false;
    }
    
    // 设置状态栏信息和进度条
    ui->statusInfo->setText(QString("正在下载文件: %1").arg(filename));
    ui->downloadProgress->setValue(0);
    ui->downloadProgress->setVisible(true);
    
    if (false == m_isPassiveMode) {
        // 1. 确保数据连接已经建立
        if (!dataServer->isListening()) {
            if (!DataConnect()) {
                ui->loginInfo->append("数据连接建立失败");
                ui->statusInfo->setText("下载失败");
                ui->downloadProgress->setVisible(false);
                return false;
            }
        }

        // 2. 发送PORT命令
        if (!PORTRequest()) {
            ui->loginInfo->append("PORT命令失败");
            ui->statusInfo->setText("下载失败");
            ui->downloadProgress->setVisible(false);
            return false;
        }
    }
    else {
        if (nullptr == dataSocket || false == m_isPassiveMode2) {
            if (!PASVRequest()) {
                ui->loginInfo->append("PASV命令失败");
                ui->statusInfo->setText("下载失败");
                ui->downloadProgress->setVisible(false);
                return false;
            }
        }
        QDir dir(ui->localPath->text());
        QString savePath = dir.absoluteFilePath(filename);
        QFile* file = new QFile(savePath);

        if (!file->open(QIODevice::WriteOnly | QIODevice::Truncate)) {
            ui->loginInfo->append("无法创建文件: " + file->errorString());
            ui->statusInfo->setText("下载失败");
            ui->downloadProgress->setVisible(false);
        }
        else {
            ui->downloadProgress->setVisible(true);
        }
        m_mapSocketFile.insert(dataSocket, file);
    }
    
    ui->loginInfo->append("-----------------------------------");
    
    // 3. 发送TYPE命令设置二进制传输
    QString typeCommand = "TYPE I\r\n";
    controlSocket->write(typeCommand.toUtf8());
    
    if (!controlSocket->waitForBytesWritten(3000)) {
        ui->loginInfo->append("发送TYPE命令错误: " + controlSocket->errorString());
        ui->statusInfo->setText("下载失败");
        ui->downloadProgress->setVisible(false);
        return false;
    }
    
    ui->loginInfo->append("发送TYPE命令成功");
    
    Respond[0] = '\0';
    // 等待服务器响应TYPE命令
    if (controlSocket->waitForReadyRead(3000)) {
        ui->loginInfo->append(Respond);
    } else {
        ui->loginInfo->append("接收TYPE响应错误: " + controlSocket->errorString());
        ui->statusInfo->setText("下载失败");
        ui->downloadProgress->setVisible(false);
        return false;
    }
    
    // 4. 发送RETR命令请求文件
    QString retrCommand = "RETR " + filename + "\r\n";
    setCurCmd(retrCommand);
    controlSocket->write(retrCommand.toUtf8());
    
    if (!controlSocket->waitForBytesWritten(3000)) {
        ui->loginInfo->append("发送RETR命令错误: " + controlSocket->errorString());
        ui->statusInfo->setText("下载失败");
        ui->downloadProgress->setVisible(false);
        return false;
    }
    
    ui->loginInfo->append(retrCommand);
    ui->loginInfo->append("发送RETR命令成功");
    
    Respond[0] = '\0';
    // 等待服务器响应RETR命令
    if (controlSocket->waitForReadyRead(3000)) {
		ui->loginInfo->append(Respond);
		int code = RespondCode(Respond);
        if (code == 150) {
            return true;
        }
		if (code < 200 || code >= 300) {
			ui->loginInfo->append("RETR命令失败，响应码: " + QString::number(code));
			ui->statusInfo->setText("下载失败");
			ui->downloadProgress->setVisible(false);
			return false;
		}
    } else {
        ui->loginInfo->append("接收RETR响应错误: " + controlSocket->errorString());
        ui->statusInfo->setText("下载失败");
        ui->downloadProgress->setVisible(false);
        return false;
    }

    return true;
}

bool MainWindow::FISTORRequest(qint64 filesize)
{
    QString typeCommand = "FISTOR " + QString::number(filesize) +"\r\n";
    controlSocket->write(typeCommand.toUtf8());
    ui->loginInfo->append("<---"+typeCommand);
    return true;
}

//bool MainWindow::STORRequest(){
//    bzero(Sendbuf,MAXSIZE);
//    bzero(Respond,MAXSIZE);
//    memcpy(Sendbuf,"STOR ",strlen("STOR "));
//    memcpy(Sendbuf+strlen("STOR "),ui->uploadpath->text().toStdString().data(),strlen(ui->uploadpath->text().toStdString().data()));
//    memcpy(Sendbuf+strlen("STOR ")+strlen(ui->uploadpath->text().toStdString().data()),"\r\n",2);
//    if(send(SocketControl,Sendbuf,strlen(Sendbuf),0)<0){
//        qDebug("send stor Request error");
//        exit(0);
//    }
//    ui->loginInfo->append(Sendbuf);
//    ui->loginInfo->append("send stor Request success");
//    if(recv(SocketControl,Respond,MAXSIZE,0)<0){
//                qDebug("socket stor receive error");
//                ui->loginInfo->append("socket stor receive error");
//    }
//    ui->loginInfo->append(Respond);
//    char src[256];
//    while(send(SocketData,src,strlen(src),0)>0){
//         bzero(src,256);
//     }
//    return true;
//}

void MainWindow::on_connectBtn_clicked()
{
    ui->statusInfo->setText("正在连接服务器...");
    bool success = ControlConnect();
    if (!success) {
        ui->statusInfo->setText("连接失败");
    }
}



void MainWindow::on_listBtn_clicked()
{
    ui->statusInfo->setText("正在设置数据连接...");
    
    bool dataConnectionSuccess = false;
    
    // 根据m_isPassiveMode变量选择使用PORT模式还是PASV模式
    if (m_isPassiveMode) {
        if (nullptr == dataSocket || false == m_isPassiveMode2) {
            ui->loginInfo->append("使用被动模式(PASV)...");
            dataConnectionSuccess = PASVRequest();
        }
        else {
            dataConnectionSuccess = true;
        }
    } else {
        ui->loginInfo->append("使用主动模式(PORT)...");
        dataConnectionSuccess = PORTRequest();
    }
    
    if (dataConnectionSuccess) {
        ui->loginInfo->append("---------------------------");
        LISTRequest();
    } else {
        ui->statusInfo->setText("设置数据连接失败");
    }
}

void MainWindow::on_login_clicked()
{
    ui->statusInfo->setText("正在登录服务器...");
    if (FTPLogin()) {
        ui->loginInfo->append("---------------------------");
        if (DataConnect()) {
            if (false == m_isPassiveMode) {
                if (PORTRequest()) {
                    ui->statusInfo->setText("登录成功，已设置主动模式(PORT)");
                    QMessageBox::information(NULL, "登录成功", "登录成功\n连接模式:主动模式(PORT)", QMessageBox::Yes);

                    // 登录成功后保存设置
                    saveSettings();
                }
            }
        }
    } else {
        ui->statusInfo->setText("登录失败");
    }
}

void MainWindow::on_quitBtn_clicked()
{
    QUITRequest();
}

//获取响应码
int MainWindow::RespondCode(char* respondcode){
    int code = 220;
    char* res = new char[3];
    memset(res,0,3);
    //strncpy(res,respondcode,3);
    memcpy(res,respondcode,3);
    code = atoi(res);
    return code;
}

//刷新本地文件列表
void MainWindow::refreshLocalFileList()
{
    QString path = ui->localPath->text();
    if (path.isEmpty()) {
        // 如果没有设置路径，使用当前工作目录
        path = QDir::currentPath();
        ui->localPath->setText(path);
    }
    loadLocalFileList(path);
}

/**
 * @brief MainWindow::saveSettings
 * 保存用户的FTP服务器设置
 */
void MainWindow::saveSettings()
{
    QSettings settings("config.ini", QSettings::IniFormat);
    
    // 保存服务器地址、用户名和密码
    settings.setValue("Server/Address", ui->address->text());
    settings.setValue("Server/Username", ui->username->text());
    settings.setValue("Local/Path", ui->localPath->text());
    
    // 加密保存密码
    if (!ui->password->text().isEmpty()) {
        QByteArray encodedPassword = ui->password->text().toUtf8();
        encodedPassword = encodedPassword.toBase64();
        settings.setValue("Server/Password", encodedPassword);
    }
    
    ui->loginInfo->append("设置已保存");
    // 保存窗口大小和位置
    settings.setValue("WindowSize", size());
    settings.setValue("WindowPosition", pos());


    settings.setValue("headerStateR", ui->fileTable->horizontalHeader()->saveState());
    settings.setValue("headerStateL", ui->localFileTable->horizontalHeader()->saveState());
#if 1
    // 保存splitter的状态
    QList<int> splitterSizes = ui->splitter->sizes();
    QStringList slist;
    for (auto& i : splitterSizes) {
        slist.push_back(QString::number(i));
    }
    settings.setValue("SplitterSizes", slist.join(","));
#endif

}

/**
 * @brief MainWindow::loadSettings
 * 加载用户的FTP服务器设置
 */
void MainWindow::loadSettings()
{
    QSettings settings("config.ini", QSettings::IniFormat);
    
    // 加载服务器地址和用户名
    ui->address->setText(settings.value("Server/Address").toString());
    ui->username->setText(settings.value("Server/Username").toString());
    m_serverPort = settings.value("Server/Port",CONNECTPORT).toUInt();
    m_isPassiveMode = settings.value("Server/PassiveMode", true).toBool();
    m_isPassiveMode2 = settings.value("Server/PassiveMode2", true).toBool();
    ui->localPath->setText(settings.value("Local/Path").toString());
    
    // 加载并解密密码
    QByteArray encodedPassword = settings.value("Server/Password").toByteArray();
    if (!encodedPassword.isEmpty()) {
        QByteArray passwordData = QByteArray::fromBase64(encodedPassword);
        ui->password->setText(QString::fromUtf8(passwordData));
    }

    // 恢复窗口大小和位置
    if (settings.contains("WindowSize")) {
        resize(settings.value("WindowSize").toSize());
    }
    if (settings.contains("WindowPosition")) {
        move(settings.value("WindowPosition").toPoint());
    }

        // 从配置加载表头宽度比例
    QByteArray headerState = settings.value("headerStateR").toByteArray();
    if (!headerState.isEmpty()) {
        ui->fileTable->horizontalHeader()->restoreState(headerState);
    }

    headerState = settings.value("headerStateL").toByteArray();
    if (!headerState.isEmpty()) {
        ui->localFileTable->horizontalHeader()->restoreState(headerState);
    }
    
    // 恢复splitter的状态
    if (settings.contains("SplitterSizes")) {
        QStringList sList = settings.value("SplitterSizes").toString().split(",");
        QList<int> sizes;
        for (const auto& i : sList) {
            sizes.push_back(i.toInt());
        }
        if (sizes.size() >= 2) {
                ui->splitter->setSizes(sizes);
        }
        else {
            // 默认分配宽度
            ui->splitter->setSizes(QList<int>() << 400 << 400);
        }
    }
    else {
        // 默认分配宽度
        ui->splitter->setSizes(QList<int>() << 400 << 400);
    }
}
